package com.hrt.datasender.web.dataMaintain;

import com.btcode.common.AbstractSingleton;
import com.btcode.common.HttpConnUtil;
import com.btcode.db.sqlparameter.SQLParameterList;
import com.btcode.exception.MsgException;
import com.btcode.json.JsonConver;
import com.btcode.orm.model.BaseModel;
import com.btcode.orm.model.IModel;
import com.btcode.orm.model.ModelPageResult;
import com.btcode.security.RSAService;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.hrt.common.web.JsonRequestUnit;
import com.hrt.datasender.datadao.model.*;
import com.hrt.datasender.datadao.service.BdSourceService;
import com.hrt.db.DBManager;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.*;

public final class DataMaintainService {

//    private String keyUrl = "https://202.105.247.6:4003/omip/api/safe/get-public-key";
//    private String tokenUrl = "https://202.105.247.6:4003/omip/api/safe/login";
//    private String uploadUrl = "https://202.105.247.6:4003/omip/api/op/pc/ddcmanager/upload-config";
//    private String downUrl = "https://202.105.247.6:4003/omip/api/op/pc/ddcmanager/download-config";
//    private String siteCodeUrl = "https://202.105.247.6:4003/omip/api/op/pc/ddcmanager/get-site-code";
    private String keyUrl = "https://dataip.szholly.com/omip.data.monitor/api/safe/get-public-key";
    private String tokenUrl = "https://dataip.szholly.com/omip.data.monitor/api/safe/login";
    private String uploadUrl = "https://dataip.szholly.com/omip.data.monitor/api/dataip/pc/ddcmanager/upload-config";
    private String downUrl = "https://dataip.szholly.com/omip.data.monitor/api/dataip/pc/ddcmanager/download-config";
    private String siteCodeUrl = "https://dataip.szholly.com/omip.data.monitor/api/dataip/pc/ddcmanager/get-site-code";
    private String username = "hollyscy";
    private String password = "Holly1234scy";

    private static volatile DataMaintainService instance;

    public static DataMaintainService getInstance() {
        if (instance == null) {
            synchronized (DataMaintainService.class) {
                if (instance == null) {
                    instance = new DataMaintainService();
                }
            }
        }
        return instance;
    }
    
    public boolean siteCodeExist(String siteCode) throws Exception {
        String token = getAccessToken();  
        String mac = getMACAddress();
        HashMap<String,String> mapPara = new HashMap<String,String>();
        NameValuePair[] nvpPara;
        mapPara.put("_token", token);
        mapPara.put("SITE_CODE",siteCode);
        mapPara.put("MAC",mac);
        nvpPara = converNameValuePair(mapPara);
        String result = HttpConnUtil.postData(siteCodeUrl, nvpPara, "utf-8");
        JsonObject httpResult = new JsonParser().parse(result).getAsJsonObject();
        JsonArray data = httpResult.getAsJsonArray("data");
        if(data.size()>0) {
            return true;
        }
        else {
            return false;
        }
    }
    
    /*
     * 获取运营平台接口权限
     * */
    public String getAccessToken() throws Exception {
        HashMap<String,String> mapPara = new HashMap<String,String>();
        NameValuePair[] nvpPara;
        /**
         * 先获取公钥,对密码进行加密
         */
        String keyStr = HttpConnUtil.postData(keyUrl, null, "utf-8");
        JsonObject keyJson = new JsonParser().parse(keyStr).getAsJsonObject();
        String key = keyJson.get("data").getAsString();
        byte[] publicKey = Base64.decodeBase64(key);
        RSAService rsa = RSAService.getInstance();
        rsa.setPublicKey(publicKey);
        String realPassWord = rsa.encryptByPublicKey(password);
        //获得token  
        mapPara.put("username", username);
        mapPara.put("password", realPassWord);
        nvpPara = converNameValuePair(mapPara);
        String result = HttpConnUtil.postData(tokenUrl, nvpPara, "utf-8");
        JsonObject httpResult = new JsonParser().parse(result).getAsJsonObject();
        String token = httpResult.getAsJsonArray("data").get(0).getAsJsonObject().get("token").getAsString();
        System.out.println(token);
        return token;
    }
    
    public String uploadConfig(String siteCode) throws Exception{
        String mac = getMACAddress();
        String token = getAccessToken();       
        HashMap<String,String> mapPara = new HashMap<String,String>();
        NameValuePair[] nvpPara; 
        //DATA
        HashMap<String,String> data = new HashMap<String,String>();
        //表名转换
        data.put("O_BD_DCC_SERIAL", converJsonArray(dataHandle(BcSerialModel.class,siteCode)));
        data.put("O_BD_DCC_SITE", converJsonArray(dataHandle(BcSiteModel.class,siteCode)));
        String sendPlatform = converJsonArray(dataHandle(BcSendPlatformModel.class,siteCode)).replaceAll("\"PLATFORM_ID\":", "\"DCC_ID\":");
        data.put("O_BD_DCC_SEND_PLATFORM", sendPlatform);
        data.put("O_BD_DCC_SEND_PARAM", converJsonArray(dataHandle(BcSendPlatformParamModel.class,siteCode)));
        data.put("O_BD_DCC_SEND_DATASTR", converJsonArray(dataHandle(BcSendPlatformDataStrategyModel.class,siteCode)));
        data.put("O_BD_DCC_DEVICES", converJsonArray(dataHandle(BcDevicesModel.class,siteCode)));
        data.put("O_BD_DCC_DEVICE_CONFIG", converJsonArray(dataHandle(BcDeviceConfigModel.class,siteCode)));
        data.put("O_BD_DCC_DEVICE_PARAM", converJsonArray(dataHandle(BcDeviceMonitorParamModel.class,siteCode)));
        data.put("O_BD_DCC_PARAM_DICT", converJsonArray(dataHandle(BcMonitorParamDictModel.class,siteCode)));
        data.put("O_BD_DCC_PARAM_MAP_212", converJsonArray(dataHandle(BcParamMap212Model.class,siteCode)));
        data.put("O_BD_DCC_ACCESS_TABLE", converJsonArray(dataHandle(BcAccessTableModel.class,siteCode)));
        data.put("O_BD_DCC_ACCESS_PARAM", converJsonArray(dataHandle(BcAccessParamModel.class,siteCode)));
        String dataStr = converJson(data);
        mapPara.clear();
        mapPara.put("_token", token);
        mapPara.put("DATA", dataStr);
        mapPara.put("SITE_CODE",siteCode);
        mapPara.put("MAC",mac);
        nvpPara = converNameValuePair(mapPara);
        String ret = HttpConnUtil.postData(uploadUrl, nvpPara, "utf-8");
        return ret;
    }

    /*
     * 数据处理
     * */
    public <T extends BaseModel> List<T> dataHandle(Class<T> modelClass,String siteCode) {
        ModelPageResult mpr = DBManager.getORMExecuter().getModelList(modelClass, null,null);
        List<T> models = mpr.getData();
        for(BaseModel model : models) {
            model.remove("CREATETIME");
            model.put("SITE_CODE", siteCode);
            model.put("VERSION", "CURRENT");
        }
        return models;
    }
    
    public static String converJsonArray(Object obj) {
        if (obj == null) {
            obj = new ArrayList<>();
        }
        else if (!(obj instanceof Collection<?>)) {
            List<Object> objList = new ArrayList<>();
            objList.add(obj);
            obj = objList;
        }
        String reuslt = AbstractSingleton.getInstance(JsonConver.class).toJson(obj);
        reuslt = reuslt.replaceAll("\"ID\":", "\"DCC_ID\":");
        return reuslt;
    }
    
    
    public NameValuePair[] converNameValuePair(HashMap<String,String> map) {
        Set<String> set = map.keySet();
        NameValuePair[] nvp = new NameValuePair[set.size()];
        int i = 0;
        for(Iterator<String> it = set.iterator();it.hasNext();) {
            NameValuePair nameValuePair = new NameValuePair();
            String key = it.next();
            nameValuePair.setName(key);
            nameValuePair.setValue(map.get(key));
            nvp[i] = nameValuePair;
            i++;
        }
        return nvp;
    }
    
    public String converJson(Object obj) {
        return AbstractSingleton.getInstance(JsonConver.class).toJson(obj);
    }
    
    public void downloadConfig(String siteCode) throws Exception{
        String token = getAccessToken();  
        //使用token访问下载配置接口       
        HashMap<String,String> mapPara = new HashMap<String,String>();
        NameValuePair[] nvpPara;
        mapPara.put("_token", token);
        mapPara.put("SITE_CODE",siteCode);
        nvpPara = converNameValuePair(mapPara);
        String ret = HttpConnUtil.postData(downUrl, nvpPara, "utf-8");
        JsonObject result = new JsonParser().parse(ret).getAsJsonObject();
        String resultFlag = result.get("result_flag").getAsString(); 
        String resultFlagDsc = result.get("result_flag_dsc").getAsString();
        if(!"SUCCESS".equals(resultFlag)) {
            throw new MsgException("下载配置失败"+resultFlagDsc);
        }
        //取到下载配置，对数据进行更新
        JsonObject data = result.getAsJsonArray("data").get(0).getAsJsonObject();     
        creates(data,"O_BD_DCC_SITE",BcSiteModel.class,BcSiteModel.tableName);
        creates(data,"O_BD_DCC_SERIAL",BcSerialModel.class,BcSerialModel.tableName);
        creates(data,"O_BD_DCC_SEND_PLATFORM",BcSendPlatformModel.class,BcSendPlatformModel.tableName);
        creates(data,"O_BD_DCC_SEND_PARAM",BcSendPlatformParamModel.class,BcSendPlatformParamModel.tableName);
        creates(data,"O_BD_DCC_SEND_DATASTR",BcSendPlatformDataStrategyModel.class,BcSendPlatformDataStrategyModel.tableName);
        creates(data,"O_BD_DCC_DEVICES",BcDevicesModel.class,BcDevicesModel.tableName);
        creates(data,"O_BD_DCC_DEVICE_CONFIG",BcDeviceConfigModel.class,BcDeviceConfigModel.tableName);
        creates(data,"O_BD_DCC_DEVICE_PARAM",BcDeviceMonitorParamModel.class,BcDeviceMonitorParamModel.tableName);
        creates(data,"O_BD_DCC_PARAM_DICT",BcMonitorParamDictModel.class,BcMonitorParamDictModel.tableName);
        creates(data,"O_BD_DCC_PARAM_MAP_212",BcParamMap212Model.class,BcParamMap212Model.tableName);
        creates(data,"O_BD_DCC_ACCESS_TABLE",BcAccessTableModel.class,BcAccessTableModel.tableName);
        creates(data,"O_BD_DCC_ACCESS_PARAM",BcAccessParamModel.class,BcAccessParamModel.tableName);
    }
    
    public <T extends IModel> void creates(JsonObject data,String dataName,Class<T> modelClass,String tableName){
        String sql = "DELETE FROM "+tableName;
        DBManager.getDataExecuter().delete(sql,null);
        String dataStr = data.get(dataName).toString();
        if("O_BD_DCC_SEND_PLATFORM".equals(dataName)) {
            dataStr = dataStr.replaceAll("\"DCC_ID\":", "\"PLATFORM_ID\":");
        }
        else {
            dataStr = dataStr.replaceAll("\"DCC_ID\":", "\"ID\":");
        }  
        List<T> models = JsonRequestUnit.getPureModels(modelClass, dataStr);
        DBManager.getORMExecuter().creates(models); 
    }
    
    public BcConfigStorageModel getModel() {
        ModelPageResult mpr = DBManager.getORMExecuter().getModelList(BcConfigStorageModel.class, null,null);
        List<BcConfigStorageModel> models = mpr.getData();

        if (models == null) {
            return null;
        }

        if (models.size() > 0) {
            return models.get(0);
        }

        return null;
    }

    public void save(BcConfigStorageModel model) {

        BcConfigStorageModel vmodel = null;

        if (model.getId() != null) {
            vmodel = DBManager.getORMExecuter().getModel(model);
        }

        if (vmodel == null) {
            DBManager.getORMExecuter().create(model);
        }
        else {
            DBManager.getORMExecuter().update(model);
        }
    }
    
    //获取MAC地址的方法  
    private String getMACAddress(){  
        final int maskCode = 0xFF;
        InetAddress ia;
        try {
            ia = InetAddress.getLocalHost();
            byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();   
            StringBuffer sb = new StringBuffer();  
            for(int i=0;i<mac.length;i++){  
                if(i!=0){  
                    sb.append("-");  
                }  
                String s = Integer.toHexString(mac[i] & maskCode);  
                sb.append(s.length()==1?0+s:s);  
            }  
            return sb.toString().toUpperCase();  
        } 
        catch (Exception e) {
            e.printStackTrace();
            return null;
        } 
    }

    public void readLogData(String path) throws IOException{
        //根据文件路径加载数据
        File file = new File(path);
        List<BdSourceModel> models  = txt2Models(file);
        models = BdSourceService.getInstance().unitConver(models);

        //删除库里数据，重新录入
        Date start = models.get(0).getDatatime();
        Date end = models.get(models.size()-1).getDatatime();
        String sql = "delete from BD_SOURCE" +
                " where DATATIME >=@START and DATATIME <=@END";
        SQLParameterList pc = new SQLParameterList();
        pc.put("START", start);
        pc.put("END", end);
        DBManager.getDataExecuter().delete(sql,pc);

        List<BdSourceModel> modelList = new ArrayList<BdSourceModel>();
        for (int i = 0; i < models.size(); i++) {
            modelList.add(models.get(i));
            if(modelList.size()==100){
                DBManager.getORMExecuter().creates(modelList);
                modelList.clear();
            }
        }
        if(modelList.size()>0){
            DBManager.getORMExecuter().creates(modelList);
        }
    }


    public static List<BdSourceModel> txt2Models(File file){
        List<BdSourceModel> models = new ArrayList<BdSourceModel>();
        try{
            BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
            String s = null;
            while((s = br.readLine())!=null){//使用readLine方法，一次读一行
                if(s.startsWith("[DATATIME]:")){
                    //构建BD_SOURCE  model
                    BdSourceModel model = new BdSourceModel();
                    HashMap<String,String> map = new HashMap<String,String>();
                    String[] array = s.split(",");
                    //datatime
                    String datatime = array[0].replace("[DATATIME]:","");
                    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
                    Date date = sdf.parse(datatime);
                    model.setDatatime(date);
                    //[MEAS_RE]
                    String measRe = array[2].replace("[MEAS_RE]:","");
                    model.setMeasRe(Double.parseDouble(measRe));
                    //[DATA_ID]
                    String dataId = array[3].replace("[DATA_ID]:","");
                    model.setDataId(dataId);
                    //[PARAM_CODE_BUS]
                    String paramCodeBus = array[5].replace("[PARAM_CODE_BUS]:","");
                    model.setParamCodeBus(paramCodeBus);
                    //[DATATIME_TEXT]
                    String dataTimeText = array[6].replace("[DATATIME_TEXT]:","");
                    model.setDatatimeText(dataTimeText);
                    models.add(model);
                }
            }
            br.close();
        }catch(Exception e){
            e.printStackTrace();
            throw new MsgException("读取日志数据错误"+e);
        }
        return models;
    }

}
